/*
 * ruletangle.h
 *
 *  Created on: Jun 25, 2011
 *      Author: Mo
 */

#ifndef RULETANGLE_H_
#define RULETANGLE_H_

#include "rectangle.h"

/** This class represents a set of rectangles that cover all the coordinates with the same "if-part" in their
 *  rules. There will be a pair of LongInstances with the same "if-part" (or long neighborhood) and opposite
 *  label. The coordinates of both longinstances will be covered by the rectangles in this class. Each rectangle
 *  will have only one longinstance, meaning the next state (expressed in the "then-part" of the rule) is the same
 *  for all of them. The rectangles will be divided into 2 vectors. Each vector holds the rectangles whose longinstance
 *  are the same. i.e. The longinstance of te all rectangles in the first vector have the same label. The rule
 *  will be then: if [coordinate has this long neighborhood] AND belongs to a rectangle in the first vector of
 *  rectangles, the output is 0. it is 1 if it belongs to the second vector of rectangles. *
 */
class Ruletangle
{
private:
	LongInstance majorLongInstance;		//!< The longinstance usually with the more coordinates (not guaranteed that its more)
	LongInstance minorLongInstance;
	vector<Rectangle> majorRectangle;	//!< The set of rectangles whose longinstance are the same. DO WE NEED THIS??
	vector<Rectangle> minorRectangle; 	//!< The set of rectangles with different label than above

	/**
	 * Adds a coordinate to the set of minor rectangles and updates both major and minor set of rectangles.
	 * This function will automatically divide the major rectangles if necessary, and create or expand a
	 * minor rectangle to include the recently added coordinate.
	 */
	void addMinorCoo (const Coordinate& coo);

	/**
	 * This function updates the vector of major rectangles by dividing the single major rectangle who surrounds the 
	 * given coordination. Nothing will be done if no major rectangle surrounds the given coordination. The vector 
	 * of major rectangles will be automatically updated. 
	 * \return the number of new rectangles. -1 if error happens, 0 if no major rectangle surrounds the coo, 2, 3 or 4
	 * if rectangle needs to break down.
	 * NOTE: It is not very optimized now. It divides in 8 new rectangles without merging those who can be merged.
	 * remember to merge them later.
	 */
	int divideMajorsOn (const Coordinate& coo);

public:
	Ruletangle(void);
	Ruletangle(const Ruletangle& other);
	Ruletangle(const LongInstance& l1, const LongInstance& l2);	//!< NOTE: l1 and l2 are conflicting rules, with the same IF part and different lable
	Ruletangle(const LongInstance& l); //!< C'tor with only one LongInstance parameter. Assumes there is no conflicting rule.
	~Ruletangle();


	/** Returns true is the given coordination exists in one of the sub-rectangles. */
	bool hasCoo (const Coordinate& coo);

	/** returns the label of the given coordination.
	 *  This functions finds the rule (i.e.)long instance that includes the given coordination
	 *  and returns the rule label (then-part) for it.
	 */
	int label (const Coordinate& coo) const;

	/**
	 * Returns true if the given IF part (as a Neighborhood vector) is the same as the IF part in this Ruletangle object.
	 * i.e. if the rule of the ruletangle applies to this sample.
	 */
	bool applies (const vector<Neighborhood*>& nbr) const;

	/**
	 * Returns the number of rectangles in the major set.
	 */
	int getMajorRectNum () const {return this->majorRectangle.size();}

	/**
	 * Returns the number of minor rectangles.
	 */
	int getMinorRectNum () const {return this->minorRectangle.size();}

	/**
	 * returns the number of coordinates in the major longinstance (whose label is dominant)
	 */
	int getMajorCooNum () const {return this->majorLongInstance.getOccuranceNum();}

	/**
	 * returns the number of coordinates in the minor longinstance (whose label is dominant)
	 */
	int getMinorCooNum () const {return this->minorLongInstance.getOccuranceNum();}

	/** Returns the major rectangle whose index is given.*/
	Rectangle getMajorRect (int index) const {return Rectangle(this->majorRectangle[index]);}

	/** Returns the minor rectangle whose index is given.*/
	Rectangle getMinorRect (int index) const {return Rectangle(this->minorRectangle[index]);}
		
	/** 
	 * Returns the amount of information for all the coordinates and rectangles stored in the object.
	 * it adds 2 per coo and 4 per rectangle.
	 */
	int getNetInfoSizeInBits(void);

	/** Prints the content of the object to the screen. */
	void print(void) const;

	/** Prints the detailed content of the object to the screen. */
	void printDetail(void) const;
};

#endif /* RULETANGLE_H_ */
